package com.mes.task.dao;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.bstek.dorado.data.provider.Page;
import com.mes.common.dao.BasicDao;
import com.mes.task.dao.iface.IOperationTaskDao;
import com.mes.task.domain.OperationTask;
import com.mes.task.domain.PartTask;

@Repository
public class OperationTaskDao extends BasicDao<OperationTask> implements IOperationTaskDao {

	private final static Log log = LogFactory.getLog(OperationTaskDao.class);

	/**
	 * 获取某一零件任务指定状态的工序任务
	 * 
	 * @param parentTaskUid
	 * @param taskState
	 * @return
	 */
	public List<OperationTask> getOperationTasksByParentUid(String parentTaskUid, int taskState) {
		List list = null;
		try {

			Session session = this.getSession();
			Criteria crit = session.createCriteria(OperationTask.class);
			crit.add(Restrictions.eq("parentTaskUid", parentTaskUid));
			crit.add(Restrictions.eq("taskState", taskState));
			crit.addOrder(Property.forName("operationId").asc());
			list = crit.list();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

	@Override
	public List<OperationTask> getOperationTasksByParentUid(String parentTaskUid) {
		List list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(OperationTask.class);
			crit.add(Restrictions.eq("parentTaskUid", parentTaskUid));
			crit.addOrder(Property.forName("operationId").asc());
			list = crit.list();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

	@Override
	public List<OperationTask> getOperationTasksByParentUid(String parentTaskUid, Float operationId) {
		List list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(OperationTask.class);
			crit.add(Restrictions.eq("parentTaskUid", parentTaskUid));
			crit.add(Restrictions.gt("operationId", operationId));
			crit.addOrder(Property.forName("operationId").asc());
			list = crit.list();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}
	
	/**
	 * 获取某个零件任务下顺序号大于operationId的工序任务
	 * 
	 * @param partTaskUid
	 *            零件任务Uuid
	 * @param operationId
	 *            工序OperationId应该大于的值
	 * @param isDesc
	 *            是否按照operaitonId倒排序
	 * @return
	 */
	@Override
	public List<OperationTask> getOperationTasksByPartTaskUid(String partTaskUid, Double operationId, Boolean isDesc) {
		List list = null;
		try {
			Session session = this.getSessionFactory().getCurrentSession();
			Criteria crit = session.createCriteria(OperationTask.class);
			crit.add(Restrictions.eq("parentTaskUid", partTaskUid));
			crit.add(Restrictions.gt("operationId", operationId));

			if (isDesc) {
				crit.addOrder(Property.forName("operationId").desc());
			} else {
				crit.addOrder(Property.forName("operationId").asc());
			}
			list = crit.list();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * 获取某个零件任务下的所有工序任务
	 * 
	 * @param partTaskUid
	 *            零件任务Uuid
	 * @param isDesc
	 *            是否按照operaitonId倒排序
	 * @return
	 */
	@Override
	public List<OperationTask> getOperationTasksByPartTaskUid(String partTaskUid, Boolean isDesc) {
		List list = null;
		try {
			Session session = this.getSessionFactory().getCurrentSession();
			Criteria crit = session.createCriteria(OperationTask.class);
			crit.add(Restrictions.eq("parentTaskUid", partTaskUid));

			if (isDesc) {
				crit.addOrder(Property.forName("operationId").desc());
			} else {
				crit.addOrder(Property.forName("operationId").asc());
			}
			list = crit.list();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * 查找某个零件任务下的厂外协作工序
	 * 
	 * @param partTaskUid
	 * @return
	 */
	@Override
	public List<OperationTask> getWaixieOperationTasksByPartTaskUid(String partTaskUid) {
		List<OperationTask> list = new ArrayList();
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(OperationTask.class);
			crit.add(Restrictions.like("workCenterUid", "wxcj%"));
			crit.add(Restrictions.eq("parentTaskUid", partTaskUid));
			crit.addOrder(Property.forName("operationId").asc());
			list = crit.list();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	@Override
	public List<OperationTask> getWipOperationTasks(String masterShopUid, Integer from, Integer size) {
		List list = null;
		try {
			Session session = this.getSession();
			StringBuilder hql = new StringBuilder();
			hql.append("from " + OperationTask.class.getName() + " where ");
			hql.append(" taskState<209 and parentTask.taskState<106 ");
			hql.append("  and parentTask.masterShopUid like ? || '%' ");
			Query query = session.createQuery(hql.toString());
			query.setString(0, masterShopUid);
			if (from != null && size != null && from >= 0 && size >= 0) {
				query.setFirstResult(from);
				query.setMaxResults(size);

			}
			list = query.list();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return list;
	}

	@Override
	public OperationTask getOperationTask(String partUid, String batchNum, String operationIddesc) {
		List list = null;
		try {
			Session session = this.getSession();
			StringBuilder hql = new StringBuilder();
			hql.append("from " + OperationTask.class.getName() + " where ");
			hql.append(" partUid=? and batchNum=? and operationIdDesc=? ");
			Query query = session.createQuery(hql.toString());
			query.setString(0, partUid);
			query.setString(1, batchNum);
			query.setString(2, operationIddesc);
			list = query.list();
			if (list != null && list.size() > 0)
				return (OperationTask) list.get(0);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public OperationTask getCurrentOperationTask(String partUid, String batchNum) throws Exception {
		List<OperationTask> list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(OperationTask.class);
			crit.add(Restrictions.eq("partUid", partUid));
			crit.add(Restrictions.eq("batchNum", batchNum));
			crit.addOrder(Property.forName("operationId").asc());
			list = crit.list();

			int size = list.size();
			if (list != null && size > 0) {
				for (int i = 0; i < size; i++) {
					if (list.get(i).getTaskState() < OperationTask.TASKSTATE_COMPLETED) {
						return list.get(i);
					}
				}
				return list.get(size - 1);
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}



	/**
	 * 取得某道工序之前的未完工序任务
	 */
	public List<OperationTask> getUnFinishTasksByPartTask(String partTaskUid, Float beforeOperationId)
			throws Exception {
		List list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(OperationTask.class);
			crit.add(Restrictions.eq("parentTaskUid", partTaskUid));
			crit.add(Restrictions.lt("taskState", OperationTask.TASKSTATE_COMPLETED));
			if (beforeOperationId != null)
				crit.add(Restrictions.lt("operationId", beforeOperationId));
			crit.addOrder(Property.forName("operationId").asc());
			list = crit.list();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;
	}

	@Override
	public List<OperationTask> getUnFinishTasksByPartTask(String partTaskUid) throws Exception {
		List list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(OperationTask.class);
			crit.add(Restrictions.eq("parentTaskUid", partTaskUid));
			crit.add(Restrictions.lt("taskState", OperationTask.TASKSTATE_COMPLETED));
			crit.addOrder(Property.forName("operationId").asc());
			list = crit.list();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;
	}

	public List<OperationTask> getCanFeedbackOperationTasks(String partUid, String batchNum) throws Exception {
		List list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(OperationTask.class);
			crit.add(Restrictions.eq("partUid", partUid));
			crit.add(Restrictions.eq("batchNum", batchNum));
			crit.add(Restrictions.lt("taskState", OperationTask.TASKSTATE_COMPLETED));
			crit.add(Restrictions.or(Restrictions.gt("taskState", OperationTask.TASKSTATE_READY),
					Restrictions.gt("dispatchGrade", OperationTask.DispatchGrade.NEED_DISPATCH)));
			crit.addOrder(Property.forName("operationId").asc());
			list = crit.list();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * 获取汇检工序任务 created by nk
	 */
	@SuppressWarnings("unchecked")
	public List<OperationTask> getSummaryCheckOperationTask(String taskType, String serviceDeptId, String drawingId,
			String batchNum, Integer taskDistance, String invDemandState) {
		List<OperationTask> list = null;

		if (drawingId == null) {
			drawingId = "";
		}

		if (batchNum == null) {
			batchNum = "";
		}

		drawingId = drawingId.replace("*", "%");
		batchNum = batchNum.replace("*", "%");

		try {
			Session session = this.getSession();
			Criteria criteria = session.createCriteria(OperationTask.class);

			criteria.add(Restrictions.eq("taskType", taskType));
			criteria.add(Restrictions.lt("taskState", 209));
			criteria.add(Restrictions.gt("planQty", 0f));

			if (taskDistance <= 0) {
				// 最大默认是10道工序
				// taskDistance = 10;
				// criteria.add(Restrictions.le("taskDistance", taskDistance));
			} else {
				criteria.add(Restrictions.eq("taskDistance", taskDistance));
			}

			criteria.add(Restrictions.like("batchNum", batchNum, MatchMode.ANYWHERE));

			// 查询单据状态
			if (invDemandState == null || "".equals(invDemandState)) {
				criteria.add(Restrictions.isNull("invDemandState"));
			} else if ("*".equals(invDemandState)) {
				// 不执行任何操作
			} else {
				criteria.add(Restrictions.eq("invDemandState", invDemandState));
			}

			// 这种多层属性，要使用别称的方式
			criteria.createAlias("part", "part").add(Restrictions.like("part.drawingId", drawingId));

			String sql = "isdutydept(5, masterShop, '', '" + serviceDeptId + "') <> 0";
			criteria.add(Restrictions.sqlRestriction(sql));
			// 排序方式
			// criteria.addOrder(Order.desc("priority"));

			// 设置最大检索数量
			criteria.setMaxResults(100);
			long startTime = System.currentTimeMillis();
			list = criteria.list();

			log.info("---------------------------nk" + list.size());

			// 使用TreeSet完成排序
			TreeSet tempSet = new TreeSet(new Comparator<OperationTask>() {
				public int compare(OperationTask a, OperationTask b) {
					// 数值大的在前面
					long bp = b.getPriority() == null ? 0 : b.getPriority();
					long ap = a.getPriority() == null ? 0 : a.getPriority();

					if (bp >= ap) {
						return 1;
					} else {
						return -1;
					}
				}
			});
			tempSet.addAll(list);
			list.clear();

			for (Iterator iter = tempSet.iterator(); iter.hasNext();) {
				OperationTask temp = (OperationTask) iter.next();
				list.add(temp);
			}

			long endTime = System.currentTimeMillis();
			long costTime = endTime - startTime;
			log.info("本次getSummaryCheckOperationTask查询及排序使用的时间：" + costTime + "ms");
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	@SuppressWarnings("unchecked")
	public List<OperationTask> getOperationTaskByPrepareState(String taskType, String serviceDeptId, String masterShop,
			String drawingId, String batchNum, Integer taskDistance, String prepareState) {
		List<OperationTask> list = null;

		if (drawingId == null) {
			drawingId = "";
		}

		if (batchNum == null) {
			batchNum = "";
		}

		if (prepareState == null) {
			prepareState = "";
		}
		if (masterShop == null) {
			masterShop = "";
		}

		drawingId = drawingId.replace("*", "%");
		batchNum = batchNum.replace("*", "%");
		prepareState = prepareState.replace("*", "%");
		masterShop = masterShop.replace("*", "%");

		try {
			Session session = this.getSession();
			Criteria criteria = session.createCriteria(OperationTask.class);

			criteria.add(Restrictions.eq("taskType", taskType));
			criteria.add(Restrictions.lt("taskState", 209));

			if (taskDistance <= 0) {
				// 最大默认是10道工序
				taskDistance = 10;
				criteria.add(Restrictions.le("taskDistance", taskDistance));
			} else {
				criteria.add(Restrictions.eq("taskDistance", taskDistance));
			}

			criteria.add(Restrictions.like("batchNum", batchNum, MatchMode.ANYWHERE));
			criteria.add(Restrictions.like("masterShopUid", masterShop, MatchMode.START));
			// criteria.add(Restrictions.like("masterShop", masterShop));

			// 这种多层属性，要使用别称的方式
			criteria.createAlias("part", "part").add(Restrictions.like("part.drawingId", drawingId));

			// 确定工序任务的准备状态
			// 注意要加like的MatchMode，否则应该主动加上百分号%
			criteria.add(Restrictions.like("prepareState", prepareState, MatchMode.START));

			String sql = "isdutydept(1, masterShop, '', '" + serviceDeptId + "') <> 0 and masterShop <> '00'";
			criteria.add(Restrictions.sqlRestriction(sql));

			// 排序方式，但是加上排序方式之后，对速度影响太大
			// criteria.addOrder(Order.desc("priority"));

			// 设置最大检索数量
			criteria.setMaxResults(100);
			long startTime = System.currentTimeMillis();
			list = criteria.list();

			log.info("---------------------------nk" + list.size());

			// 使用TreeSet完成排序
			TreeSet tempSet = new TreeSet(new Comparator<OperationTask>() {
				public int compare(OperationTask a, OperationTask b) {
					// 数值大的在前面
					long bp = b.getPriority() == null ? 0 : b.getPriority();
					long ap = a.getPriority() == null ? 0 : a.getPriority();

					if (bp >= ap) {
						return 1;
					} else {
						return -1;
					}
				}
			});
			tempSet.addAll(list);
			list.clear();

			for (Iterator iter = tempSet.iterator(); iter.hasNext();) {
				OperationTask temp = (OperationTask) iter.next();
				list.add(temp);
			}

			long endTime = System.currentTimeMillis();
			long costTime = endTime - startTime;
			log.info("本次getOperationTaskByPrepareState查询及排序使用的时间：" + costTime + "ms");
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	@Override
	public List<OperationTask> getOperationTaskByPartUidAndBatchNum(String partUid, String batchNum, boolean sort,
			Page page) {
		List<OperationTask> opList = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(OperationTask.class);

			crit.add(Restrictions.eq("partUid", partUid));
			crit.add(Restrictions.eq("batchNum", batchNum));
			if (sort) {
				crit.addOrder(Property.forName("operationId").asc());
			} else {
				crit.addOrder(Property.forName("operationId").desc());
			}

			if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				opList = this.query(crit, null);
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return opList;
	}

	@Override
	public List<OperationTask> getDispatchOperationTasks(String masterShopUid, Date planStartBefore, Page page) {
		List<OperationTask> opList = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(OperationTask.class);
			crit.add(Restrictions.or(Restrictions.eq("taskState", OperationTask.TASKSTATE_DISPATCHED),
					Restrictions.like("taskState", OperationTask.TASKSTATE_STARTED)));

			crit.add(Restrictions.like("masterShopUid", masterShopUid, MatchMode.START));
			if (planStartBefore != null)
				crit.add(Restrictions.lt("planStart", planStartBefore));
			// 已开始任务在前面
			crit.addOrder(Property.forName("taskState").desc());
			crit.addOrder(Property.forName("planStart").asc());

			if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				opList = this.query(crit, null);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return opList;
	}

	/**
	 * 获取责任工序
	 * 
	 * @param dataSet
	 * @throws Exception
	 */
	@Override
	public List<OperationTask> getDutyOperationTasks(String partNumber, String batchNum, List list) throws Exception {
		try {
			if (list == null) {
				list = new ArrayList();
			}

			List list1 = null;
			Session session = this.getSession();
			Criteria crit = session.createCriteria(OperationTask.class);
			crit.add(Restrictions.eq("partUid", partNumber));
			crit.add(Restrictions.eq("batchNum", batchNum));
			crit.add(Restrictions.ge("taskState", OperationTask.TASKSTATE_COMPLETED));
			crit.addOrder(Property.forName("operationId").asc());
			list1 = crit.list();

			Iterator iter = list1.iterator();
			while (iter.hasNext()) {
				list.add(iter.next());
			}

			crit = session.createCriteria(PartTask.class);
			crit.add(Restrictions.eq("partUid", partNumber));
			crit.add(Restrictions.eq("batchNum", batchNum));
			PartTask partTask = (PartTask) crit.uniqueResult();
			if (partTask != null) {
				crit = session.createCriteria(PartTask.class);
				crit.add(Restrictions.eq("partUid", partNumber));
				crit.add(Restrictions.eq("batchNum", partTask.getRootBatchNum()));
				crit.add(Restrictions.like("taskType", "1%"));
				PartTask parentPartTask = (PartTask) crit.uniqueResult();

				if (parentPartTask != null) {
					this.getDutyOperationTasks(partNumber, partTask.getRootBatchNum(), list);
				}
			}

		} catch (Exception e) {
			System.out.println("OperationTaskDAOImpl获取责任工序出错");
			e.printStackTrace();
		}
		return list;
	}

	@Override
	public List<OperationTask> getAOOperationTask(String taskUid) {
		List<OperationTask> opList = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(OperationTask.class);

			crit.add(Restrictions.eq("parentTaskUid", taskUid));
			crit.add(Restrictions.lt("taskState", 209));
			opList = crit.list();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return opList;
	}

	@Override
	public void getOperationTaskByCondition(Page<OperationTask> page, Map<String, Object> params) throws Exception {
		Map<String, Object> args = new HashMap<String, Object>();
		StringBuffer coreHql = new StringBuffer("from OperationTask a where 1=1 ");

		if (params != null){
			//批次
			String batchNum = (String) params.get("batchNum");
			if (StringUtils.isNotEmpty(batchNum)) {
				coreHql.append(" and a.batchNum like :batchNum ");
				args.put("batchNum", "%" + batchNum + "%");
			}
			
			//图号
			String partDrawingId = (String) params.get("partDrawingId");
			if (StringUtils.isNotEmpty(partDrawingId)) {
				coreHql.append(" and a.partDrawingId like :partDrawingId ");
				args.put("partDrawingId", "%" + partDrawingId + "%");
			}
			
			//名称
			String taskName = (String) params.get("taskName");
			if (StringUtils.isNotEmpty(taskName)) {
				coreHql.append(" and a.taskName like :taskName ");
				args.put("taskName", "%" + taskName + "%");
			}
			
			//工序
			String operationIdDesc = (String) params.get("operationIdDesc");
			if (StringUtils.isNotEmpty(operationIdDesc)) {
				coreHql.append(" and operationIdDesc like :operationIdDesc ");
				args.put("operationIdDesc", "%" + operationIdDesc + "%");
			}
		}
		
		
		String countHql = "select count(*) " + coreHql.toString();
		String hql = coreHql.toString();
		
		Map<String, Object> newArgs = new HashMap<String, Object>();
		String key;
		String newKey;
		Iterator<String> iterator = args.keySet().iterator();
		while(iterator.hasNext()){
			key = (String)iterator.next();
			newKey = key.replace(".", "_");
			newArgs.put(newKey, args.get(key));
			hql = hql.replace(":"+key, ":"+newKey);
			countHql = countHql.replace(":"+key, ":"+newKey);
		}
		this.pagingQuery(page, hql, countHql, newArgs);
		
	}

}
